﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BitPortal.Models;
using BitPortal.Utils;
using System.Configuration;
using System.Web.Configuration;
using System.Xml;
using System.Linq.Expressions;
using System.IO;
namespace BitPortal.Business
{
    public static partial class ModuleBLL
    {
        public class ModuleIcon
        {
            public string Icon {set;get;}
            public string Name { set; get; }
            public string Url { set; get; }
            public string Code { set; get; }
        }

        /// <summary>
        /// Đọc các module có thể setup từ dường dẫn thư mục đưa vào
        /// </summary>
        /// <param name="listModules"></param>
        /// <param name="path"></param>
        public static void ListSourceModules(List<ModuleBLL.ModuleIcon> listModules, string path = "~/Modules", bool isVirtuaPath = true)
        {
            string serverPath = isVirtuaPath ? HttpContext.Current.Server.MapPath(path) : path;
            DirectoryInfo di = new DirectoryInfo(serverPath);
            if (di.Exists)
            {
                FileInfo[] files = di.GetFiles();
                ModuleIcon mi = new ModuleIcon();
                foreach (FileInfo file in files)
                {
                    if (file.Extension.ToLower().Equals(".ico"))
                    {
                        mi.Icon = Utils.FileUtils.GetVirtualPath(file.FullName);
                        mi.Name = file.Name.Replace(".ico","");
                    }
                    else if (file.Extension.ToLower().Equals(".ascx"))
                    {
                        mi.Code = file.Name.Replace(".ascx","");
                    }
                    else if (file.Extension.ToLower().Equals(".config"))
                    {
                        mi.Url = Utils.FileUtils.GetVirtualPath(file.FullName);
                    }
                }
                if (!(string.IsNullOrEmpty(mi.Name) || string.IsNullOrEmpty(mi.Url) || string.IsNullOrEmpty(mi.Code) || string.IsNullOrEmpty(mi.Icon)))
                {
                    listModules.Add(mi);
                }
                DirectoryInfo[] dirs = di.GetDirectories();
                foreach (DirectoryInfo dir in dirs)
                {
                    ListSourceModules(listModules, dir.FullName, false);
                }
            }
        }
        /// <summary>
        /// Đọc các module có thể setup từ dường dẫn thư mục đưa vào
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<ModuleIcon> GetListSourceModules(string path = "~/Modules", bool isVirtualPath = true)
        {
            List<ModuleIcon> list = new List<ModuleIcon>();
            ListSourceModules(list, path, isVirtualPath);
            return list;
        }

        public static ModuleBase ReadBaseModuleConfig(string modulePath)
        {
            XmlDocument config = new XmlDocument();
            config.Load(HttpContext.Current.Server.MapPath(modulePath));
            Models.ModuleBase mb = new ModuleBase();
            mb.Name = config.SelectSingleNode("//configuration/ModuleConfig/Key").InnerText;
            mb.Description = config.SelectSingleNode("//configuration/ModuleConfig/Description").InnerText;
            mb.Path = modulePath;
            foreach (XmlNode node in config.SelectNodes("//configuration/ModuleConfig/Properties/Property"))
            {
                BaseModuleConfig bcf = new BaseModuleConfig();
                bcf.Name = node.SelectSingleNode("Name").InnerText;
                bcf.DataType = node.SelectSingleNode("Type").InnerText;
                bcf.Value = node.SelectSingleNode("Default").InnerText;
                bcf.AllowUserConfig = Convert.ToBoolean(node.SelectSingleNode("AllowUserConfig").InnerText);
                mb.BaseModuleConfigs.Add(bcf);
            }
            return mb;
        }

        public static object GetBaseModuleConfigValue(this ModuleBase mb, string key)
        {
            return mb.BaseModuleConfigs.SingleOrDefault(ent => ent.Name == key).Value;
        }

        public static ModuleBase GetBaseModuleByID(object id)
        {
            int _id = Utils.GeneralUtils.ToInt32TryParse(id);
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            return bitEnt.ModuleBases.SingleOrDefault(ent => ent.ModuleBaseID == _id);
        }

        public static Module GetModuleByID(object id)
        {
            int _id = Utils.GeneralUtils.ToInt32TryParse(id);
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            return bitEnt.Modules.SingleOrDefault(ent => ent.ModuleID == _id);
        }

        public static object GetModuleConfig(this Module module, string key)
        {

            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            var obj = from configValue in module.ModuleConfigs
                      from config in bitEnt.BaseModuleConfigs
                      where configValue.ConfigID == config.ConfigID && config.Name == key
                      select configValue.Value;
            if (obj.ToList().Count == 0)
            {
                return GetBaseModuleConfigValue(module.ModuleBas, key);
            }
            return (obj.ToList().First());
        }

        public static int Insert(this ModuleBase mb)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            if (bitEnt.ModuleBases.Count(ent => ent.Name == mb.Name) > 0)
            {
                throw new Exception("Module đã được cài đặt!");
            }
            bitEnt.ModuleBases.AddObject(mb);
            return bitEnt.SaveChanges();
        }

        public static int Insert(this Module module)
        {
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            bitEnt.Modules.AddObject(module);
            return bitEnt.SaveChanges();
        }

        public static int DeleteBaseModuleByID(object id)
        {
            int _id = Utils.GeneralUtils.ToInt32TryParse(id);
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            ModuleBase mb = bitEnt.ModuleBases.SingleOrDefault(ent => ent.ModuleBaseID == _id);
            if (mb != null)
            {
                bitEnt.ModuleBases.DeleteObject(mb);
                return bitEnt.SaveChanges();
            }
            return 0;
        }

        public static int DeleteModuleByID(object id)
        {
            int _id = Utils.GeneralUtils.ToInt32TryParse(id);
            ExtendedBitPortalEntities bitEnt = new ExtendedBitPortalEntities();
            Module mb = bitEnt.Modules.SingleOrDefault(ent => ent.ModuleID == _id);
            if (mb != null)
            {
                bitEnt.Modules.DeleteObject(mb);
                return bitEnt.SaveChanges();
            }
            return 0;
        }

        public static IQueryable<ModuleBase> GetAllBaseModule()
        {
            return (new ExtendedBitPortalEntities()).ModuleBases;
        }

        public static IQueryable<Module> GetAllPageModule()
        {
            return (new ExtendedBitPortalEntities()).Modules;
        }

        public static string GetPath(this Models.Module module)
        {
            return module.ModuleBas.GetPath();
        }

        public static string GetPath(this Models.ModuleBase baseModule)
        {
            return baseModule.Path.Replace("Module.config", baseModule.Name + ".ascx");
        }

        public static IQueryable<Module> GetModuleByCondition<T>(string languageCode = null, bool? onAllPage = null, bool? isEnabled = null, int? pageId = null, int start = -1, int limit = -1, string sort = "SortOrder", string dir = "DESC")
        {
            var list = GetAllPageModule().Where(ent =>
                (languageCode == null || ent.LanguageCode == languageCode) &&
                (onAllPage == null || ent.OnAllPage == onAllPage) &&
                (isEnabled == null || ent.IsEnabled == isEnabled) &&
                (pageId == null || ent.PageID == pageId)
                );
            //Start Sorting
            if (sort != null)
            {
                var param = Expression.Parameter(typeof(Module), "ent");
                var sortExpression = Expression.Lambda<Func<Module, T>>(Expression.Property(param, sort), param);
                if (sort != "ModuleID")
                {
                    if (dir == "DESC")
                    {
                        list = list.OrderByDescending(sortExpression).ThenByDescending(ent => ent.ModuleID);
                    }
                    else
                    {
                        list = list.OrderBy(sortExpression).ThenByDescending(ent => ent.ModuleID);
                    }
                }
                else
                {
                    if (dir == "DESC")
                    {
                        list = list.OrderByDescending(ent => ent.ModuleID);
                    }
                    else
                    {
                        list = list.OrderBy(ent => ent.ModuleID);
                    }
                }
            }
            //Start Paging
            if (start >= 0 && limit > 0)
            {
                list = list.Skip(start).Take(limit);
            }
            return list;
        }
    }
}